#include "CalendarView.h"

#include <QDebug>
#include <QHeaderView>
#include <QKeyEvent>
#include <QPainter>
#include <QSvgRenderer>
#include <QImage>

const QString offset = "      ";

CalendarView::CalendarView(QWidget *parent) :
    QTableView(parent)
{
    setTabKeyNavigation(false);
    setShowGrid(true);
    setMouseTracking(true);
    verticalHeader()->setVisible(false);
    horizontalHeader()->setVisible(false);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setSelectionBehavior(QAbstractItemView::SelectItems);
    setSelectionMode(QAbstractItemView::SingleSelection);
    horizontalHeader()->setResizeMode(QHeaderView::Stretch);
    horizontalHeader()->setClickable(false);
    verticalHeader()->setResizeMode(QHeaderView::Stretch);
    verticalHeader()->setClickable(false);
    setFrameStyle(QFrame::NoFrame);
}

void CalendarView::setModel(QAbstractItemModel *model)
{
    QTableView::setModel(model);
    m_delegate = new CalendarDelegate(this);
    setItemDelegate(m_delegate);
    connect(this, SIGNAL(sendEvent(QEvent *, const QModelIndex &, const QRect &, bool &)),
            m_delegate, SLOT(runEvent(QEvent *, const QModelIndex &, const QRect &, bool &)));
    connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            m_delegate, SLOT(updateData(QModelIndex,QModelIndex)));
    // hardcode
//    openPersistentEditor(this->model()->index(2, 7));
    resizeColumnsToContents();
    horizontalHeader()->setResizeMode(0, QHeaderView::Fixed);
    horizontalHeader()->resizeSection(0, 20);
    verticalHeader()->setResizeMode(0, QHeaderView::Fixed);
    verticalHeader()->resizeSection(0, 20);
    m_delegate->updateData(model->index(0, 0), model->index(model->rowCount() - 1, model->columnCount() - 1));
}

void CalendarView::wheelEvent(QWheelEvent *event)
{
    const QModelIndex &index = currentIndex();
    bool needUpdate = false;
    emit sendEvent(event, index, visualRect(index), needUpdate);
    update(index);
}

void CalendarView::showEvent(QShowEvent *event)
{
    qDebug() << "showEvent";
    const QModelIndex &index = currentIndex();
    bool needUpdate = false;
    emit sendEvent(event, index, visualRect(index), needUpdate);
}

QModelIndex CalendarView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
{
    QModelIndex index = currentIndex();
    CalendarModel *calendarModel = dynamic_cast<CalendarModel *>(model());
    if (!calendarModel) {
        qDebug() << "MODEL NOT VALID!!!";
        return QModelIndex();
//        return QTableView::moveCursor(cursorAction, modifiers);
//        return currentIndex();
    }
    QDate currentDate = calendarModel->dateForCell(index.row(), index.column());
    QDate newDate = currentDate;
    qDebug() << "currentDate: " << currentDate.toString("yyyyMMdd");

    switch (cursorAction) {
    case QAbstractItemView::MoveUp:
        newDate = newDate.addDays(-7);
        break;
    case QAbstractItemView::MoveDown:
        newDate = newDate.addDays(7);
        break;
    case QAbstractItemView::MoveLeft:
        newDate = newDate.addDays(isRightToLeft() ? 1 : -1);
        break;
    case QAbstractItemView::MoveRight:
        newDate = newDate.addDays(isRightToLeft() ? -1 : 1);
        break;
    case QAbstractItemView::MoveHome:
        newDate = QDate(newDate.year(), newDate.month(), 1);
        break;
    case QAbstractItemView::MoveEnd:
        newDate = QDate(newDate.year(), newDate.month(), newDate.daysInMonth());
        break;
    case QAbstractItemView::MovePageUp:
        newDate = newDate.addMonths(-1);
        break;
    case QAbstractItemView::MovePageDown:
        newDate = newDate.addMonths(1);
        break;
    case QAbstractItemView::MoveNext:
    case QAbstractItemView::MovePrevious:
        return currentIndex();
        break;
    default:
        break;
    }

//    if (newDate.month() == currentDate.month()
//            && newDate.year() == currentDate.year())
//    {
        QModelIndex newIndex = calendarModel->cellForDate(newDate);
        if (newIndex.isValid()) {
            qDebug() << "by index";
            changeSelection(newIndex);
        } else {
            qDebug() << "by date with update";
            changeSelection(newDate, true);
        }
//    }

    return QModelIndex();
}

//void CalendarView::update()
//{
//    CalendarModel *calendarModel = dynamic_cast<CalendarModel *>(model());
//    if (!calendarModel)
//        return;
//    QDate currentDate = calendarModel->date();
//    int row, column;
//    calendarModel->cellForDate(currentDate, &row, &column);
//    QModelIndex idx;
//    selectionModel()->clear();
//    if (row != -1 && column != -1) {
//        idx = calendarModel->index(row, column);
//        selectionModel()->setCurrentIndex(idx, QItemSelectionModel::SelectCurrent);
//    }
//}

//void CalendarView::keyPressEvent(QKeyEvent *event)
//{
////    if (!readOnly) {
//        switch (event->key()) {
//            case Qt::Key_Return:
//            case Qt::Key_Enter:
//            case Qt::Key_Space:
//            case Qt::Key_Select:
////                emit editingFinished();
//                break;
//            default:
//                break;
//        }
////    }
//    QTableView::keyPressEvent(event);
//}

//bool CalendarView::event(QEvent *event)
//{
//    return QTableView::event(event);
//}

//QDate CalendarView::handleMouseEvent(const QPoint &pos)
//{
//    CalendarModel *calendarModel = dynamic_cast<CalendarModel *>(model());
//    QModelIndex index = indexAt(pos);
//    qDebug() << "Clicked index: " << index;
//    QDate date = calendarModel->dateForCell(index.row(), index.column());
//    if (date.isValid() && date >= calendarModel->minimumDate()
//        && date <= calendarModel->maximumDate()) {
//        return date;
//    }
//    return QDate();
//}

//void CalendarView::mouseDoubleClickEvent(QMouseEvent *event)
//{
//    QDate date = handleMouseEvent(event->pos());
//    if (date.isValid()) {
//        int row = -1, col = -1;
//        static_cast<CalendarModel *>(model())->cellForDate(date, &row, &col);
//        if (row != -1 && col != -1) {
//            qDebug() << "dbl click:" + date.toString("dd-MM-yyyy");
//        }
//    } else {
//        qDebug() << "header dbl click";
//    }
//}

void CalendarView::changeSelection(const QDate &date, bool updateModel)
{
    CalendarModel *calendarModel = dynamic_cast<CalendarModel *>(model());
    if (!calendarModel) {
        qDebug() << "NO  calendarModel!!!";
        return;
    }
    if (!date.isValid()) {
        qDebug() << "Date not Valid!";
        return;
    }
    if (updateModel) {
        calendarModel->setDate(date);
        qDebug() << "calendarModel->setDate()";
    }
    qDebug() << "Date: " << date.toString("yyyyMMdd");
    QModelIndex dateIndex = calendarModel->cellForDate(date);
    if (dateIndex.isValid()) {
        qDebug() << "Date index: " << dateIndex;
        setCurrentIndex(dateIndex);
    } else {
        qDebug() << "Date index NOT VALID!!!";
    }
}

void CalendarView::changeSelection(const QModelIndex &index)
{
    CalendarModel *calendarModel = dynamic_cast<CalendarModel *>(model());
    if (!calendarModel) {
        qDebug() << "NO  calendarModel!!!";
        return;
    }
    QDate date = index.data(CalendarModel::DATE).toDate();
    if (!date.isValid()) {
        qDebug() << "Date not Valid!";
        return;
    }
    bool anotherMonth = index.data(CalendarModel::DAY_OF_ANOTHER_MONTH).toBool();
    bool updateModel = (anotherMonth
                        && date >= calendarModel->minimumDate()
                        && date <= calendarModel->maximumDate());
    changeSelection(date, updateModel);
}

void CalendarView::mousePressEvent(QMouseEvent *event)
{
    QModelIndex index = indexAt(event->pos());
    if (!index.isValid()) {
        qDebug() << "index not valid!!!";
        return;
    }
    qDebug() << "Clicked index: " << index;
    QTableView::mousePressEvent(event);
    changeSelection(index);
}

//void CalendarView::mouseMoveEvent(QMouseEvent *event)
//{
//    QDate curDate = handleMouseEvent(event->pos());
////    eventHint->moveHint(event->globalPos(), curDate);
//    if (curDate.isValid())
//        QTableView::mouseMoveEvent(event);

////    event->ignore();

////    CalendarModel *calendarModel = dynamic_cast<CalendarModel *>(model());
////    if (!calendarModel) {
////        QTableView::mouseMoveEvent(event);
////        return;
////    }
////    if (readOnly)
////        return;
//}

//void CalendarView::mouseReleaseEvent(QMouseEvent *event)
//{
//    CalendarModel *calendarModel = dynamic_cast<CalendarModel *>(model());
//    if (!calendarModel) {
//        QTableView::mouseReleaseEvent(event);
//        return;
//    }

//    if (event->button() != Qt::LeftButton)
//        return;

////    if (readOnly)
////        return;

//    if (validDateClicked) {
//        QDate date = handleMouseEvent(event->pos());
//        if (date.isValid()) {
//            emit changeDate(date, true);
//            emit clicked(date);
//            if (style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick))
//                emit editingFinished();
//            QTableView::mouseReleaseEvent(event);
//        }
//        validDateClicked = false;
//    } else {
//        event->ignore();
//    }
//}


EventListView::EventListView(const EventList_t &list, const QRect &rect)
    : m_list(list),
      m_rect(rect)
{
}

QList<Zone> EventListView::calcZones(const EventSelector &selector, const QDate &date) const
{
    QList<Zone> zones;

    QFont font;
    font.setPixelSize(11);
    int eventHeight = QFontMetrics(font).height();

    int totalHeight = eventHeight + 2;
    int i = 1;
    int v = 1;
//    bool haveFooter = false;
    foreach (const Event &event, m_list) {
        bool visible = true;
        if (v++ < selector.firstVisible && selector.selectDate == event.begin().date()) {
            visible = false;
            --i;
        }
        if (m_list.size() > 1 && !(selector.selectDate == event.begin().date()
                                      && selector.selectNumber == i))
        {
            bool hasTail = (event.end().date() > event.begin().date() && event.begin().date() == date);
            const int tailWidth = 16;
            const int tailHeigth = tailWidth;
            QRect eventRect(m_rect.x(),
                            m_rect.y() + (eventHeight + 2) * i,
                            m_rect.width() - 1 - tailWidth,
                            eventHeight + 2);
            Zone zoneEventHeader;
            zoneEventHeader.visible = visible;
            zoneEventHeader.rect = eventRect;
            zoneEventHeader.type = Zone::EventHeader;
            zoneEventHeader.event = event;
            zoneEventHeader.order = i;
            zones.push_back(zoneEventHeader);

            if (hasTail) {
                QRect tailRect(eventRect.topRight().x() + 1,
                               eventRect.topRight().y() + 1,
                               tailWidth, tailHeigth);
                Zone zoneEventTail;
                zoneEventTail.visible = visible;
                zoneEventTail.rect = tailRect;
                zoneEventTail.type = Zone::EventTail;
                zoneEventTail.event = event;
                zoneEventTail.order = i;
                zones.push_back(zoneEventTail);
            }

            ++i;
            totalHeight += eventHeight + 2;
        } else {
            QImage image;
            if (!image.load("../src/gui/" + event.imagePath())) {
                qDebug() << "can't load '../src/gui/" + event.imagePath() << "'";
            }

            int newImageWidth = m_rect.width();
            int newImageHeight = m_rect.width() * image.height() / image.width();
            if (m_rect.height() > newImageHeight) {
                newImageHeight = m_rect.height();
                newImageWidth = newImageHeight * image.width() / image.height();
            }

            QRect imageRect(m_rect.x(),
                            m_rect.y() + (eventHeight + 2),
                            newImageWidth,
                            newImageHeight);

            zones.clear();
            Zone zoneEventImage;
            zoneEventImage.visible = visible;
            zoneEventImage.rect = imageRect;
            zoneEventImage.type = Zone::EventImage;
            zoneEventImage.event = event;
            zones.push_back(zoneEventImage);

            QRect imageBorderRect(m_rect.x(),
                                  m_rect.y() + (eventHeight + 2) * 2,
                                  m_rect.width() - 1,
                                  m_rect.height() - 1 - (eventHeight + 2) * 2);

            Zone zoneEventImageBorder;
            zoneEventImageBorder.visible = visible;
            zoneEventImageBorder.rect = imageBorderRect;
            zoneEventImageBorder.type = Zone::EventImageBorder;
            zoneEventImageBorder.event = event;
            zoneEventImageBorder.order = -1;
            zones.push_back(zoneEventImageBorder);

            QRect eventRect(m_rect.x(),
                            m_rect.y() + (eventHeight + 2),
                            m_rect.width() - 1,
                            eventHeight + 2);

            Zone zoneEventHeader;
            zoneEventHeader.visible = visible;
            zoneEventHeader.rect = eventRect;
            zoneEventHeader.type = Zone::EventImageHeader;
            zoneEventHeader.event = event;
            zoneEventHeader.order = i;
            zones.push_back(zoneEventHeader);

            int j = 0;
            foreach (const Event &footerEvent, m_list) {
                if (event == footerEvent) {
                    ++j;
                    continue;
                }
                QRect footerRect(m_rect.x() + (eventHeight + 2) * j,
                                 m_rect.y() + m_rect.height() - (eventHeight + 3),
                                 eventHeight + 2,
                                 eventHeight + 2);

                Zone zoneEventFooter;
                zoneEventFooter.visible = visible;
                zoneEventFooter.rect = footerRect;
                zoneEventFooter.type = Zone::Footer;
                zoneEventFooter.event = footerEvent;
                zoneEventFooter.order = j + 1;
                zones.push_back(zoneEventFooter);

                QImage icon;
                if (!icon.load("../src/gui/" + footerEvent.iconPath())) {
                    qDebug() << "can't load '../src/gui/" + footerEvent.iconPath() << "'";
                }

                QRect iconRect(footerRect.topLeft().x() + 1,
                               footerRect.topLeft().y(),
                               16, 16);

                Zone zoneEventFooterIcon;
                zoneEventFooterIcon.visible = visible;
                zoneEventFooterIcon.rect = iconRect;
                zoneEventFooterIcon.type = Zone::FooterIcon;
                zoneEventFooterIcon.event = footerEvent;
                zoneEventFooterIcon.order = j + 1;
                zones.push_back(zoneEventFooterIcon);

                ++j;
            }

            break;
        }
    }
    return zones;
}

void EventListView::paint(QPainter *painter, const EventSelector &selector, const QDate &date) const
{
    QFont font;
    font.setPixelSize(11);
    painter->setFont(font);
    painter->setPen(QColor("black"));

    const QList<Zone> &zones = calcZones(selector, date);
    foreach (const Zone &zone, zones) {
        if (!zone.visible) {
            continue;
        }
        if (zone.type == Zone::EventHeader || zone.type == Zone::EventImageHeader) {
            painter->fillRect(zone.rect, QBrush(QColor(255, 0, 0, 127), Qt::SolidPattern));
            painter->drawRect(zone.rect);
            painter->drawText(zone.rect, offset + zone.event.name(), QTextOption(Qt::AlignLeft));

            paintEventIcon(painter, zone.event.iconPath(), zone.rect.topLeft());
            painter->drawText(zone.rect, QString::number(zone.order), QTextOption(Qt::AlignLeft));
        } else if (zone.type == Zone::EventImage) {
            QImage image;
            if (!image.load("../src/gui/" + zone.event.imagePath())) {
                qDebug() << "can't load '../src/gui/" + zone.event.imagePath() << "'";
            }
            painter->drawImage(zone.rect, image);
        } else if (zone.type == Zone::EventImageBorder) {
            painter->setPen(QColor("black"));
            painter->drawRect(zone.rect);
        } else if (zone.type == Zone::EventTail) {
            painter->setPen(QColor("black"));
            painter->drawText(zone.rect, ">", QTextOption(Qt::AlignRight));
        } else if (zone.type == Zone::Footer) {
            painter->fillRect(zone.rect, QBrush(QColor(255, 0, 0, 127), Qt::SolidPattern));
            painter->drawRect(zone.rect);
            painter->drawText(zone.rect, offset + zone.event.name(), QTextOption(Qt::AlignLeft));
        } else if (zone.type == Zone::FooterIcon) {
            QImage icon;
            if (!icon.load("../src/gui/" + zone.event.iconPath())) {
                qDebug() << "can't load '../src/gui/" + zone.event.iconPath() << "'";
            }
            painter->drawImage(zone.rect, icon);
            painter->drawText(zone.rect, QString::number(zone.order), QTextOption(Qt::AlignLeft));
        } else if (zone.type == Zone::Particle) {
            painter->fillRect(zone.rect, QBrush(QColor(255, 0, 0, 127), Qt::SolidPattern));
            painter->drawRect(zone.rect);
        }
    }
}

void EventListView::mousePressEvent(QMouseEvent *event, EventSelector &selector, const QDate &date)
{
    const QList<Zone> &zones = calcZones(selector, date);

    foreach (const Zone &zone, zones) {
        if (zone.type == Zone::EventHeader) {
            qDebug() << "Zone::EventHeader:"
                     << zone.rect
                     << ", order: " << zone.order << ", event = " << zone.event.name();
        } else if (zone.type == Zone::EventImage) {
            qDebug() << "Zone::EventImage";
        } else if (zone.type == Zone::EventImageBorder) {
//            qDebug() << "Zone::EventImageBorder";
        } else if (zone.type == Zone::Footer) {
            qDebug() << "Zone::Footer:"
                     << zone.rect
                     << ", order: " << zone.order << ", event = " << zone.event.name();
        } else if (zone.type == Zone::FooterIcon) {
//            qDebug() << "Zone::FooterIcon";
        } else if (zone.type == Zone::Particle) {
            qDebug() << "Zone::Particle";
        }
    }

    foreach (const Zone &zone, zones) {
        if (zone.type == Zone::EventHeader)
        {
            if (zone.rect.contains(event->pos())) {
                qDebug() << "i = " << zone.order << "event = " << zone.event.name();
                selector.selectNumber = zone.order;
                break;
            }
        } else if (zone.type == Zone::Footer
                   || zone.type == Zone::FooterIcon)
        {
            if (zone.rect.contains(event->pos())) {
                qDebug() << "i = " << zone.order << "FOOTER event = " << zone.event.name();
                selector.selectNumber = zone.order;
                break;
            }
        } else if (zone.type == Zone::EventImage
                   || zone.type == Zone::EventImageBorder)
        {
            selector.firstVisible = 1;
        } else if (zone.type == Zone::Particle) {
//            if (zone.rect.contains(event->pos())) {
//                qDebug() << "event paaart!";
//                break;
//            }
        }
    }
}

bool EventListView::mouseWheelEvent(QWheelEvent *event, EventSelector &selector, const QDate &date)
{
    const QList<Zone> &zones = calcZones(selector, date);
    selector.maxVisible = int(m_rect.height() / 15) - 1;

    int count = 0;
    foreach (const Zone &zone, zones) {
        if (zone.type == Zone::EventHeader) {
            ++count;
        }
    }
//            qDebug() << "Zone::EventHeader:"
//                     << zone.rect
//                     << ", order: " << zone.order << ", event = " << zone.event.name();
//        } else if (zone.type == Zone::EventImage) {
//            qDebug() << "Zone::EventImage";
//        } else if (zone.type == Zone::EventImageBorder) {
////            qDebug() << "Zone::EventImageBorder";
//        } else if (zone.type == Zone::Footer) {
//            qDebug() << "Zone::Footer:"
//                     << zone.rect
//                     << ", order: " << zone.order << ", event = " << zone.event.name();
//        } else if (zone.type == Zone::FooterIcon) {
////            qDebug() << "Zone::FooterIcon";
//        } else if (zone.type == Zone::Particle) {
//            qDebug() << "Zone::Particle";
//        } else if (zone.type == Zone::BottomScroll) {
//            qDebug() << "Zone::BottomScroll";
//        }
//    }

    foreach (const Zone &zone, zones) {
        if (zone.type == Zone::EventHeader)
        {
            int delta = event->delta() / 8 / 15;
            int newFirstVisible = selector.firstVisible - delta;
            if (newFirstVisible > 0
                    && newFirstVisible <= count - selector.maxVisible + 1)
            {
                selector.firstVisible = newFirstVisible;
                return true;
            }
            break;
        } else if (zone.type == Zone::Footer
                   || zone.type == Zone::FooterIcon)
        {
            ;
        } else if (zone.type == Zone::EventImage
                   || zone.type == Zone::EventImageBorder)
        {
            ;
        } else if (zone.type == Zone::Particle) {
            ;
        }
    }
    return false;
}

//void EventListView::paintEventHeader(QPainter *painter, const int order, const Event &event,
//                                        const QRect &rect, int eventHeight) const
//{
//    QRect eventRect(rect.x(),
//                    rect.y() + (eventHeight + 2) * order,
//                    rect.width() - 1,
//                    eventHeight + 2);
//    painter->fillRect(eventRect, QBrush(QColor(255, 0, 0, 127), Qt::SolidPattern));
//    painter->drawRect(eventRect);
//    painter->drawText(eventRect, offset + event.name(), QTextOption(Qt::AlignLeft));

//    paintEventIcon(painter, event.iconPath(), eventRect.topLeft());
//}

//void EventListView::paintEvent(QPainter *painter, const Event &event,
//                                  const QRect &rect, int eventHeight) const
//{
//    QImage image;
//    if (!image.load("../src/gui/" + event.imagePath())) {
//        qDebug() << "can't load '../src/gui/" + event.imagePath() << "'";
//    }

//    int newImageWidth = rect.width();
//    int newImageHeight = rect.width() * image.height() / image.width();
//    if (rect.height() > newImageHeight) {
//        newImageHeight = rect.height();
//        newImageWidth = newImageHeight * image.width() / image.height();
//    }

//    QRect imageRect(rect.x(),
//                    rect.y() + (eventHeight + 2),
//                    newImageWidth,
//                    newImageHeight);
//    painter->drawImage(imageRect, image);
//    painter->setPen(QColor("black"));

//    QRect imageBorderRect(rect.x(),
//                          rect.y() + (eventHeight + 2) * 2,
//                          rect.width() - 1,
//                          rect.height() - 1 - (eventHeight + 2) * 2);
//    painter->drawRect(imageBorderRect);

//    painter->setPen(QColor("black"));


////    // animation
////    int testWidth = 0;
////    if (selector.selectDate == event.begin().date()) {
////        testWidth = selector.width;
////        qDebug() << "selector.width = " << testWidth;
////    }
////    if (testWidth <= 0) {
////        testWidth = rect.width() - 1;
////        qDebug() << "rect.width() - 1 = " << testWidth;
////    }
////    qDebug() << "testWidth = " << testWidth;

//    paintEventHeader(painter, 1, event, rect, eventHeight);
//}

//void EventListView::paintEventFooterSelector(QPainter *painter, const EventList_t &eventList,
//                                                const Event &currentEvent, const QRect &rect,
//                                                int eventHeight) const
//{
//    int j = 0;
//    foreach (const Event &footerEvent, eventList) {
//        if (currentEvent == footerEvent) {
//            ++j;
//            continue;
//        }
//        QRect footerRect(rect.x() + (eventHeight + 2) * j,
//                         rect.y() + rect.height() - (eventHeight + 3),
//                         eventHeight + 2,
//                         eventHeight + 2);
//        painter->fillRect(footerRect, QBrush(QColor(0, 255, 0, 127), Qt::SolidPattern));
//        painter->drawRect(footerRect);
//        paintEventIcon(painter, footerEvent.iconPath(), footerRect.topLeft());
//        ++j;
//    }
//}

void EventListView::paintEventIcon(QPainter *painter, const QString &iconPath, const QPoint &point) const
{
    QImage icon;
    if (!icon.load("../src/gui/" + iconPath)) {
        qDebug() << "can't load '../src/gui/" + iconPath << "'";
    }

    QRect iconRect(point.x() + 1,
                   point.y(),
                   16, 16);
    painter->drawImage(iconRect, icon);
}

CalendarDelegate::CalendarDelegate(QObject *parent)
    : QItemDelegate(parent)
{
    widget = new QWidget(dynamic_cast<QWidget *>(parent));
}

//void CalendarDelegate::resizeEvent()
//{
//    qDebug() << "resizeEvent";
//    QFont font;
//    font.setPixelSize(11);
//    int eventHeight = QFontMetrics(font).height();
//    if (selector.width > eventHeight) {
//        --selector.width;
//    } else {
//        qDebug() << "stop";
//        timer.stop();
//    }
//    if (selector.index.isValid()) {
//        qDebug() << "selector.index.isValid()";
//        CalendarView *view = qobject_cast<CalendarView *>(parent());
//        view->update(selector.index);
//    }
//}

void CalendarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
                             const QModelIndex &index) const
{
    QDate date = index.data(CalendarModel::DATE).toDate();
    if (date.isValid()) {
        // clear
        painter->fillRect(option.rect, QBrush(QColor("white"), Qt::SolidPattern));

        bool isWeekend = index.data(CalendarModel::WEEKEND).toBool();
        bool isDayOfAnotherMonth = index.data(CalendarModel::DAY_OF_ANOTHER_MONTH).toBool();

        // paint background
        if (isDayOfAnotherMonth) {
            painter->fillRect(option.rect, QBrush(QColor(200, 200, 200, 120), Qt::SolidPattern));
        } else {
            painter->fillRect(option.rect, QBrush(QColor("white"), Qt::SolidPattern));
        }

        // paint event
        QVariant data = index.data(CalendarModel::EVENT);
        if (data.isValid()) {
//            EventListView listView(data.value<EventList_t>(), option.rect);
//            listView.paint(painter, m_selector, date);
//            label->render(painter, option.rect.topLeft());
            QLabel *label = widgetList.find(date).value();
            label->render(painter, option.rect.topLeft());
        }

        // paint weather
//        if (date == QDate(2011, 07, 01)) {
//            paintWeather(painter, option);
//        }

        // paint date
        paintDate(painter, option, date, isWeekend, isDayOfAnotherMonth);

        // paint current date
        paintCurrent(painter, option, date);

        // paint cursor
        paintCursor(painter, option);

        // paint focus
//        drawFocus(painter, option, option.rect.adjusted(0, 0, 0, 0));
    } else {
//        painter->setFont(headerFont(option.rect.height()));

        // paint headers
        // paint background
        paintHeader(painter, option);

        // paint week number
        QVariant data;
        data = index.data(CalendarModel::WEEK);
        if (data.isValid()) {
            // paint text
            int week = data.toInt();
            paintWeekNumber(painter, option, week);
            return;
        }

        // paint days of week
        data = index.data(CalendarModel::DAY_OF_WEEK);
        if (data.isValid()) {
            // paint text
            QString dayOfWeek = data.toString();
            bool isWeekend = index.data(CalendarModel::WEEKEND).toBool();
            paintDayOfWeek(painter, option, dayOfWeek, isWeekend);
            return;
        }
    }
}

void CalendarDelegate::paintDate(QPainter *painter, const QStyleOptionViewItem &option,
                                 const QDate &date, bool isWeekend, bool isDayOfAnotherMonth) const
{
    painter->setFont(dateFont(33));
//    painter->setFont(dateFont(option.rect.height()));
    QFontMetrics fm(painter->font());
    QString monthName = (date.day() == 1 || (date.daysInMonth() - date.day()) == 0)
                        ? date.toString("MMM")
                        : QString();
    int dateBGWidth = fm.width(QString::number(date.day()) + " " + monthName + " ");
    int dateBGHeight = fm.height();
//    QRect dateBackground(option.rect.x() + option.rect.width() - dateBGWidth - 2,
//                         option.rect.y(),
//                         dateBGWidth + 2, dateBGHeight);
//    painter->fillRect(dateBackground, QBrush(QColor(200, 200, 200, 127), Qt::SolidPattern));
//    painter->setPen(QColor("black"));
//    painter->drawRect(dateBackground);

    QRect dateBackground(option.rect.x(),
                         option.rect.y(),
                         option.rect.x() + option.rect.width(), dateBGHeight + 2);
    painter->fillRect(dateBackground, QBrush(QColor(200, 200, 200, 127), Qt::SolidPattern));

    if (isDayOfAnotherMonth) {
        painter->setPen(QColor("white"));
    } else {
        if (isWeekend) {
            painter->setPen(QColor("red"));
        } else {
            painter->setPen(QColor("black"));
        }
    }
    painter->drawText(option.rect, QString::number(date.day()) + " " + monthName + " ", QTextOption(Qt::AlignRight));
}

void CalendarDelegate::paintCurrent(QPainter *painter, const QStyleOptionViewItem &option, const QDate &date) const
{
    if (date == QDate::currentDate()) {
        painter->setPen(QPen(QBrush(QColor(0, 0, 255, 200)), 1));
        painter->drawRect(option.rect.adjusted(0, 0, -1, -1));
//        painter->fillRect(option.rect, QBrush(painter->pen().color(), Qt::BDiagPattern));
    }
}

void CalendarDelegate::paintCursor(QPainter *painter, const QStyleOptionViewItem &option) const
{
    if (option.state & QStyle::State_Selected) {
        QRect cursorRect(option.rect.x() + 1,
                         option.rect.y() + 1,
                         option.rect.width() - 2,
                         option.rect.height() - 2);
        painter->setPen(QPen(QBrush(QColor(0, 0, 255, 200)), 2));
        painter->drawRect(cursorRect);
//        painter->fillRect(option.rect, QBrush(QColor(0, 200, 0, 127), Qt::SolidPattern));
    }
}

void CalendarDelegate::paintCounter(QPainter *painter, const QStyleOptionViewItem &option) const
{
//    painter->setFont(counterFont(option.rect.height()));
//    QFontMetrics fm(painter->font());
//    QString text = QString::number(5) + " ";
//    int dateWidth = fm.width(text);
//    int dateHeight = fm.height();
//    QRect eventBackground(option.rect.x(),
//                         option.rect.y() + option.rect.height() - dateHeight,
//                         dateWidth, dateHeight);
//    painter->fillRect(eventBackground, QBrush(QColor(200, 200, 200, 127), Qt::SolidPattern));
//    painter->setPen(QColor("black"));
//    painter->drawText(eventBackground, text);
}

void CalendarDelegate::paintWeather(QPainter *painter, const QStyleOptionViewItem &option) const
{
    QString dayTemp = " +28";
    painter->setPen("black");
    painter->setFont(dayTempFont(option.rect.height()));
    painter->drawText(option.rect, "\n" + dayTemp, QTextOption(Qt::AlignVCenter | Qt::AlignLeft));

    // TODO: Move metrics to resizeEvent
    QFontMetrics fm(painter->font());
    int textWidth = fm.width(dayTemp);

    QString nightTemp = " +20";
    painter->setPen("grey");
    painter->setFont(nightTempFont(option.rect.height()));
    painter->drawText(option.rect, nightTemp, QTextOption(Qt::AlignBottom | Qt::AlignLeft));

    QRect imgRect(option.rect.x() + option.rect.width() - (option.rect.height() / 3 + option.rect.height() / 10),
                  option.rect.y() + option.rect.height() - (option.rect.height() / 3 + option.rect.height() / 10),
                  option.rect.height() / 3 + option.rect.height() / 10,
                  option.rect.height() / 3 + option.rect.height() / 10);
    painter->drawImage(imgRect, QImage(":/weather/sunny"));

    int minCellSize = textWidth + imgRect.width();
    CalendarView *calendarView = qobject_cast<CalendarView *>(parent());
    calendarView->horizontalHeader()->setMinimumSectionSize(minCellSize);

//            painter->drawRect(QRect(option.rect.x() + option.rect.width() - imgRect.width(),
//                                    option.rect.y(),
//                                    imgRect.width(), imgRect.height()));

//            qDebug() << "imgRect(" << imgRect.width() << ", " << imgRect.height() << ")";

//            QRect imgRect2(option.rect.x() + option.rect.width() - (option.rect.height() / 3 + option.rect.height() / 10),
//                           option.rect.y() + option.rect.height() - (option.rect.height() / 3 + option.rect.height() / 10)
//                           - (option.rect.height() / 3 + option.rect.height() / 10),
//                           option.rect.height() / 3 + option.rect.height() / 10,
//                           option.rect.height() / 3 + option.rect.height() / 10);
//            painter->drawImage(imgRect2, QImage(":/weather/cloudy"));
//            painter->drawRect(imgRect2);
}

void CalendarDelegate::paintWeekNumber(QPainter *painter, const QStyleOptionViewItem &option, int week) const
{
    painter->setPen(QColor("black"));
    painter->drawText(option.rect, QString::number(week), QTextOption(Qt::AlignCenter));
}

void CalendarDelegate::paintDayOfWeek(QPainter *painter, const QStyleOptionViewItem &option,
                                      const QString &dayOfWeek, bool isWeekend) const
{
    if (isWeekend) {
        painter->setPen(QColor("red"));
    } else {
        painter->setPen(QColor("black"));
    }
    painter->drawText(option.rect, dayOfWeek, QTextOption(Qt::AlignCenter));
}

void CalendarDelegate::paintHeader(QPainter *painter, const QStyleOptionViewItem &option) const
{
    painter->setPen(QColor("grey"));
    painter->fillRect(option.rect, QBrush(painter->pen().color(), Qt::SolidPattern));
}

QFont CalendarDelegate::headerFont(int cellHeight) const
{
    QFont font;
    font.setPixelSize(cellHeight / 2 - (cellHeight / 10));
    return font;
}

QFont CalendarDelegate::dateFont(int cellHeight)  const
{
    QFont font;
    font.setPixelSize(cellHeight / 3);
    return font;
}

QFont CalendarDelegate::counterFont(int cellHeight) const
{
    QFont font;
    font.setPixelSize(cellHeight / 4 + cellHeight / 15);
    return font;
}

QFont CalendarDelegate::dayTempFont(int cellHeight) const
{
    QFont font;
    font.setPixelSize(cellHeight / 4);
    return font;
}

QFont CalendarDelegate::nightTempFont(int cellHeight) const
{
    QFont font;
    font.setPixelSize(cellHeight / 5);
    return font;
}

QWidget *CalendarDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                                        const QModelIndex &index) const
{
    qDebug() << "createEditor";
    return widget;
}

bool CalendarDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
                                   const QStyleOptionViewItem &option,
                                   const QModelIndex &index)
{
    if (event->type() == QEvent::MouseButtonPress) {
        QDate date = index.data(CalendarModel::DATE).toDate();
        if (date.isValid()) {
            qDebug() << "Click date: " << date.toString("yyyyMMdd");
            qDebug() << "Selected date: " << m_selector.selectDate.toString("yyyyMMdd");
            qDebug() << "Selected number: " << m_selector.selectNumber;

            if (m_selector.selectDate != date) {
                m_selector.selectDate = date;
                m_selector.selectNumber = -1;
                m_selector.firstVisible = 1;
//                selector.index = QModelIndex();
//                selector.index = index;
//                selector.width = selectRect.width() - 1;
//                timer.start(10);
                return QItemDelegate::editorEvent(event, model, option, index);
            }

            QVariant data = index.data(CalendarModel::EVENT);
            if (data.isValid()) {
                QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
                EventListView listView(data.value<EventList_t>(), option.rect);
                listView.mousePressEvent(mouseEvent, m_selector, date);
                return true;
            }
        }
    }

    return QItemDelegate::editorEvent(event, model, option, index);
}

void CalendarDelegate::runEvent(QEvent *event, const QModelIndex &index, const QRect &rect, bool &needUpdate)
{
    if (event->type() == QEvent::Wheel) {
        QDate date = index.data(CalendarModel::DATE).toDate();
        if (date.isValid()) {
            QVariant data = index.data(CalendarModel::EVENT);
            if (data.isValid()) {
                QWheelEvent *wheelEvent = dynamic_cast<QWheelEvent *>(event);
//                qDebug() << "Wheel delta = " << wheelEvent->delta() / 8 / 15;
                EventListView listView(data.value<EventList_t>(), rect);
                needUpdate = listView.mouseWheelEvent(wheelEvent, m_selector, date);
//                label->setText(QString::number(wheelEvent->delta()));
            }
        }
    } else if (event->type() == QEvent::Show) {
        qDebug() << "runEvent: SHOW";
    }
}

void CalendarDelegate::updateData(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    qDebug("updateData...");
    const CalendarModel *calendarModel = dynamic_cast <const CalendarModel *>(topLeft.model());
    if (!calendarModel) {
        qDebug() << "MODEL NOT VALID!!!";
        return;
    }
    qDebug() << "topLeft: (" << topLeft.row() << "," << topLeft.column() << ")";
    qDebug() << "bottomRight: (" << bottomRight.row() << "," << bottomRight.column() << ")";
    widgetList.clear();
    for (int column = topLeft.column(); column < bottomRight.model()->columnCount(); ++column) {
        for (int row = topLeft.row(); row < bottomRight.model()->rowCount(); ++row) {
            const QModelIndex &index = calendarModel->index(row, column);
            QDate date = index.data(CalendarModel::DATE).toDate();
            if (!date.isValid()) {
                continue;
            }
            QVariant data = index.data(CalendarModel::EVENT);
            if (!data.isValid()) {
                continue;
            }
            QLabel *label = new QLabel("TESTOVIIIIIIIICH: " + date.toString("ddMM"));
            label->setStyleSheet("QLabel { "
                                 "background: red; "
                                 "border: 2px outset red; "
                                 "} ");
            widgetList.insert(date, label);
        }
    }
}

//    QDate date = index.data(CalendarModel::DATE).toDate();
//    if (date.isValid()) {
//        // paint event
//        QVariant data = index.data(CalendarModel::EVENT);
//        if (data.isValid()) {
//            const EventList_t &eventList = data.value<EventList_t>();
//            qDebug() << "eventList.size() = " << eventList.size();
//            foreach (const Event &event, eventList) {
//                if (event.imagePath() == "holiday.png") {
//                    qDebug() << date.toString("yyyyMMdd");
//                }
//            }
//        }
//    }

//    if (date.isValid()) {
//        QSqlRecord rec = eventModel->record();
//        filterModel->setFilterFixedString(date.toString("MM-dd"));
//        filterModel->setFilterKeyColumn(rec.indexOf("FullEventDate"));
//        QDate dbdate = filterModel->index(0, rec.indexOf("FullEventDate")).data().toDate();
//        int rowCount = filterModel->rowCount();
//        if (event->type() == QEvent::MouseMove) {
//            if (date.toString("MM-dd") == dbdate.toString("MM-dd")
//                && rowCount > 1) {
//                if (focusedDate != date) {
//                    focusedDate = date;
//                    repaintRect(option.rect);
//                }
//            } else {
//                if (focusedDate != CoreUtils::nullDate()) {
//                    focusedDate = CoreUtils::nullDate();
//                    repaintRect(option.rect);
//                }
//            }
//            return false;
//        }

//        if (event->type() == QEvent::MouseButtonPress) {
//            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
//            if (date.toString("MM-dd") == dbdate.toString("MM-dd")
//                && rowCount > 1) {
//                QRect rect = option.rect;
//                rect.setSize(QSize(11, 11));
//                if (rect.contains(mouseEvent->pos())) {
//                    qDebug() << "MouseButtonPress";
//                    int rowIndex = 0;
//                    bool FirstInList = false;
//                    if (rowCount > 1)
//                        while (rowIndex < rowCount) {
//                        FirstInList = filterModel->index(rowIndex, rec.indexOf("FirstInList")).data().toBool();
//                        if (FirstInList) break;
//                        rowIndex++;
//                    }
//                    int keyValue = filterModel->index(rowIndex, rec.indexOf("EventId")).data().toInt();
//                    nextEvent(date, keyValue);
//                }
//            }
//            return false;
//        }
//    } else
//        return QItemDelegate::editorEvent(event, model, option, index);

//    return true;
//}

//bool CalendarDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
//                                   const QStyleOptionViewItem &option,
//                                   const QModelIndex &index)
//{
//    CalendarModel *calendarModel = qobject_cast<CalendarModel *>(model);
//    QDate date = calendarModel->dateForCell(index.row(), index.column());
//    if (date.isValid()) {
////        qDebug() << "editorEvent: date.isValid()";
//        if (event->type() == QEvent::MouseMove) {
////            qDebug() << "editorEvent: MouseMove";
//            return false;
//        }

//        if (event->type() == QEvent::MouseButtonPress) {
//            QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
//            QRect rect = option.rect;
//            rect.setSize(QSize(11, 11));
//            if (rect.contains(mouseEvent->pos())) {
//                qDebug() << "editorEvent: MouseButtonPress";
//            }
//            return false;
//        }
//    } else {
//        return QItemDelegate::editorEvent(event, model, option, index);
//    }

//    return true;
//}

//void CalendarDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
//                                            const QModelIndex &index) const
//{
//    QWidget *widget = qobject_cast<QWidget *>(parent());
//    editor->setGeometry(widget->x() + option.rect.x() - 10,
//                        widget->y() + option.rect.y(),
//                        option.rect.width() + 20,
//                        option.rect.height());
//}
